package com.meis.widget.particle;

import com.meis.widget.ResourceTable;
import com.meis.widget.utils.AttrUtils;
import ohos.agp.components.AttrSet;
import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.graphics.SurfaceOps;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by wenshi on 2018/7/5.
 * Description 浮点粒子控件
 */
public class FireflyView extends SurfaceProvider implements SurfaceOps.Callback {

    // 粒子的最大数量
    private static final int MAX_NUM = 400;
    private static final int EMPTY_FLAG = 1;
    // 粒子集合
    private List<FloatParticle> mListParticles;
    // 随机数
    private SecureRandom mRandom;
    private SurfaceOps mHolder = null;
    // 动画线程
    private EventHandler mHandler;
    // 粒子半径
    private int mParticleMaxRadius;
    // 粒子数量
    private int mParticleNum;
    // 粒子移动速率
    private int mParticleMoveRate;
    private boolean isLandscape = false;

    public FireflyView(Context context) {
        this(context, null);
    }

    public FireflyView(Context context, AttrSet attrs) {
        this(context, attrs, "");
    }

    public FireflyView(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 关闭硬件加速
//        setLayerType(LAYER_TYPE_SOFTWARE, null);
        init();
        if (attrs!=null){
            mParticleMaxRadius = AttrUtils.getIntegerFromAttr(attrs, "firefly_max_radius", 5);
            mParticleNum = AttrUtils.getIntegerFromAttr(attrs, "firefly_num", MAX_NUM);
            mParticleMoveRate = AttrUtils.getIntegerFromAttr(attrs, "firefly_move_rate", 5);
        }

        try {
            PixelMap portbg = ImageSource.create(getResourceManager().getResource(
                    ResourceTable.Media_ic_firefly_bg), null).createPixelmap(null);

            Size portSize = portbg.getImageInfo().size;
            Size landSize = new Size(Math.max(portSize.width, portSize.height), Math.min(portSize.width, portSize.height));

            PixelMap.InitializationOptions opts = new PixelMap.InitializationOptions();
            opts.size = landSize;
            opts.pixelFormat = portbg.getImageInfo().pixelFormat;
            Rect srcRegion = new Rect(0, 0, portbg.getImageInfo().size.width, portbg.getImageInfo().size.height);
            PixelMap landbg = PixelMap.create(portbg, srcRegion, opts);

            addDrawTask((component, canvas) -> {
                if (isLandscape) {
                    canvas.drawPixelMapHolder(new PixelMapHolder(landbg), 0, 0, new Paint());
                } else {
                    canvas.drawPixelMapHolder(new PixelMapHolder(portbg), 0, 0, new Paint());
                }
                if (mListParticles == null) return;
                for (FloatParticle fp : mListParticles) {
                    fp.drawParticle(canvas);
                }
            });
        } catch (Exception ignored) {
        }
    }

    private void init() {
        // 设置透明
        pinToZTop(true);
        mHolder = getSurfaceOps().orElse(null);
        if (mHolder != null) {
            mHolder.setFormat(-3);
            mHolder.addCallback(this);
        }
        // 初始化随机数
        mRandom = new SecureRandom();
    }

    @Override
    public void surfaceCreated(SurfaceOps holder) {
    }

    // 初始化浮点粒子数据
    private void initParticlesData(int width, int height) {
        mListParticles = new ArrayList<>();
        for (int i = 0; i < mParticleNum; i++) {
            FloatParticle fp = new FloatParticle(width, height);
            mParticleMaxRadius = Math.max(mParticleMaxRadius, 2);
            fp.setRadius(mRandom.nextInt(mParticleMaxRadius - 1) + 1);
            mListParticles.add(fp);
        }
    }

    @Override
    public void surfaceChanged(SurfaceOps holder, int format, int width, int height) {
        initParticlesData(width, height);
        new EventHandler(EventRunner.getMainEventRunner()).postTask(this::startAnimation, 100);
    }

    @Override
    public void surfaceDestroyed(SurfaceOps holder) {
        stopAnimation();
    }

    public void stopAnimation() {
        mHandler.removeAllEvent();
    }

    public void startAnimation() {
        mHandler = new EventHandler(EventRunner.create()) {
            @Override
            protected void processEvent(InnerEvent event) {
                super.processEvent(event);
                getContext().getUITaskDispatcher().asyncDispatch(new Runnable() {
                    @Override
                    public void run() {
                        invalidate();
                    }
                });
                try {
                    Thread.sleep(10);
                } catch (InterruptedException ignored) {
                }
                mHandler.sendEvent(EMPTY_FLAG, mParticleMoveRate);
            }
        };
        mHandler.sendEvent(EMPTY_FLAG);
    }

    public int getParticleMoveRate() {
        return mParticleMoveRate;
    }

    public void setParticleMoveRate(int particleMoveRate) {
        mParticleMoveRate = particleMoveRate;
    }

    public int getParticleMaxRadius() {
        return mParticleMaxRadius;
    }

    public int getParticleNum() {
        return mParticleNum;
    }

    public void isLandscape(boolean isLandscape) {
        this.isLandscape = isLandscape;
        invalidate();
    }
}
